﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Orchard.Environment.Extensions;
using Orchard.Events;
using Orchard.Localization;
using Orchard.ContentManagement;

namespace Downplay.Audit.Rules
{
    public interface IEventProvider : IEventHandler
    {
        void Describe(dynamic describe);
    }

    [OrchardFeature("Downplay.Audit.Rules.Content")]
    public class ContentEvents : IEventProvider
    {
        public Localizer T { get; set; }

        public void Describe(dynamic describe)
        {
            Func<dynamic, bool> contentMatch = ContentMatchesContext;

            describe.For("Content", T("Content Items"), T("Content Items"))
                .Element("Displayed", T("Content Displayed"), T("Content is actually displayed."), contentMatch, (Func<dynamic, LocalizedString>)(context => T("When content with types ({0}) is displayed in {1} display.", FormatPartsList(context), FormatDisplayType(context))), "SelectContentTypesAndDisplayTypes");
        }

        private string FormatPartsList(dynamic context)
        {
            var contenttypes = context.Properties["contenttypes"];

            if (String.IsNullOrEmpty(contenttypes))
            {
                return T("Any").Text;
            }

            return contenttypes;
        }

        private string FormatDisplayType(dynamic context)
        {
            var displaytypes = context.Properties["displaytypes"];
            if (String.IsNullOrWhiteSpace(displaytypes))
            {
                return T("any").Text;
            }
            return displaytypes;
        }

        private static bool ContentMatchesContext(dynamic context)
        {
            // TODO: This will of course be executed every time any single content item is executed
            // ... so we might want to think about some optimisation.
            return ContentHasPart(context) && HasDisplayType(context);
        }

        private static bool HasDisplayType(dynamic context)
        {
            // Check display types
            string displaytypes = context.Properties["displaytypes"];
            if (String.IsNullOrWhiteSpace(displaytypes)) return true;

            var displayTypes = displaytypes.Split(new[] { ',',' ' },StringSplitOptions.RemoveEmptyEntries);
            string displayType = context.Tokens["DisplayType"];
            return displayTypes.Contains(displayType);
        }

        private static bool ContentHasPart(dynamic context)
        {
            string contenttypes = context.Properties["contenttypes"];
            var content = context.Tokens["Content"] as IContent;

            // "" means 'any'
            if (String.IsNullOrEmpty(contenttypes))
            {
                return true;
            }

            if (content == null)
            {
                return false;
            }

            var contentTypes = contenttypes.Split(new[] { ',' });

            return contentTypes.Any(contentType => content.ContentItem.TypeDefinition.Name == contentType);
        }
    }
}